package me.ingxin.android.view

import android.animation.ValueAnimator
import android.animation.ValueAnimator.AnimatorUpdateListener
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.util.AttributeSet
import android.view.View
import android.view.animation.LinearInterpolator
import me.ingxin.android.R
import kotlin.math.min

/**
 * Created by ingxin on 2022/11/26
 * 菊花loading.
 */
class LoadingView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    @Suppress("PrivatePropertyName")
    private val LINE_COUNT = 12

    @Suppress("PrivatePropertyName")
    private val DEGREE_PER_LINE = 360 / LINE_COUNT

    private val paint: Paint
    private var duration: Int

    private var animateValue = 0
    private var animator: ValueAnimator? = null
    private val updateListener = AnimatorUpdateListener { animation ->
        animateValue = animation.animatedValue as Int
        invalidate()
    }

    init {
        val a = context.obtainStyledAttributes(attrs, R.styleable.LoadingView)
        val color = a.getInt(R.styleable.LoadingView_android_color, Color.WHITE)
        duration = a.getInt(R.styleable.LoadingView_android_duration, 600)
        a.recycle()
        paint = Paint().apply {
            this.color = color
            isAntiAlias = true
            strokeCap = Paint.Cap.ROUND
        }
    }

    override fun onDraw(canvas: Canvas) {
        val size = min(width, height)

        val rotateDegrees = animateValue * DEGREE_PER_LINE.toFloat()
        val w = size / 12
        val h = size / 6
        val ox = size * 0.5f
        val oy = size * 0.5f
        paint.strokeWidth = w.toFloat()

        val saveCount = canvas.saveLayer(0f, 0f, width.toFloat(), height.toFloat(), null)

        //绕中心点旋转
        canvas.rotate(rotateDegrees, ox, oy)
        //画布顶点移到中心点
        canvas.translate(ox, oy)

        for (i in 0 until LINE_COUNT) {
            canvas.rotate(DEGREE_PER_LINE.toFloat())
            paint.alpha = (255f * (i + 1) / LINE_COUNT).toInt()
            //把画布从中心点向下偏移size/2(内容向上), w/2为直线圆角高度,需要预留出来
            canvas.translate(0f, (w / 2 - size / 2).toFloat())
            canvas.drawLine(0f, 0f, 0f, h.toFloat(), paint)
            //还原偏移量
            canvas.translate(0f, (size / 2 - w / 2).toFloat())
        }

        canvas.restoreToCount(saveCount)
    }

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        start()
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        stop()
    }

    override fun onVisibilityChanged(changedView: View, visibility: Int) {
        super.onVisibilityChanged(changedView, visibility)
        if (visibility == VISIBLE) {
            start()
        } else {
            stop()
        }
    }

    fun setColor(color: Int) {
        paint.color = color
        invalidate()
    }

    fun setDuration(duration: Int) {
        this.duration = duration
        if (animator?.isStarted == true) {
            animator?.duration = duration.toLong()
        }
    }

    fun start() {
        if (animator == null) {
            animator = ValueAnimator.ofInt(0, LINE_COUNT - 1).apply {
                addUpdateListener(updateListener)
                duration = this@LoadingView.duration.toLong()
                repeatMode = ValueAnimator.RESTART
                repeatCount = ValueAnimator.INFINITE
                interpolator = LinearInterpolator()
            }
        }
        if (animator?.isStarted != true) {
            animator?.start()
        }
    }

    fun stop() {
        animator?.let {
            it.removeUpdateListener(updateListener)
            it.removeAllUpdateListeners()
            it.cancel()
        }
        animator = null
    }

}